<?php

/**
 * @link https://www.humhub.org/
 * @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
 * @license https://www.humhub.com/licences
 */

#namespace humhub\modules\user\models;
namespace humhub\modules\api\models;

use Yii;
use yii\helpers\Url;

/**
 * This is the model class for table "user_invite".
 *
 * @property integer $id
 * @property integer $user_originator_id
 * @property integer $space_invite_id
 * @property string $email
 * @property string $source
 * @property string $token
 * @property string $created_at
 * @property integer $created_by
 * @property string $updated_at
 * @property integer $updated_by
 * @property string $language
 * @property string $firstname
 * @property string $lastname
 */
class Invite extends \yii\db\ActiveRecord
{


    //email config
    const ALI_accessKeyId     = "LTAIpILqJBDdTg48";
    const ALI_accessKeySecret = "tkkbWds1SuQ5nv7T9kiV9vO4HrTwKN";



    const SOURCE_SELF = "self";
    const SOURCE_INVITE = "invite";
    const TOKEN_LENGTH = 12;

    private $token_type = '';

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'user_invite';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['user_originator_id', 'space_invite_id', 'created_by', 'updated_by'], 'integer'],
            //[['token'], 'unique'],
            [['firstname', 'lastname'], 'string', 'max' => 255],
            [['email', 'source', 'token'], 'string', 'max' => 45],
            [['language'], 'string', 'max' => 10],
            [['email'], 'required', 'message'=>'手机号或邮箱不能为空'],
            //[['email'], 'unique', 'message'=>'手机号已被占用'],

            //[['email'], 'email'],
            //[['email'], 'unique', 'targetClass' => \humhub\modules\user\models\User::className(), 'message' => Yii::t('UserModule.base', 'E-Mail is already in use! - Try forgot password.')],

            //[['email'],'match','pattern'=>'/^(1)[0-9]{10}$/','message'=>'不是有效的手机号'],
            ['email', function ($attribute, $params){
                if( preg_match('/^(1)[0-9]{10}$/', $this->email) ){
                    $cd = User::find()->where(['mphone'=>$this->email])->one();
                    if( $this->token_type=='reg' && $cd ){
                        $this->addError($attribute, '手机号已注册');
                    }else{
                        return true;
                    }
                }else{
                    $pattern = "/^[a-z0-9]([a-z0-9]*[-_\.]?[a-z0-9]+)*@([a-z0-9]+([-_]?[a-z0-9]+)*)+([\.][a-z]{1,4}){1,3}$/i";
                    if( preg_match($pattern, $this->email) ){
                        $cd = User::find()->where(['email'=>$this->email])->one();
                        if( $this->token_type=='reg' && $cd ){
                            $this->addError($attribute, '邮箱已注册');
                        }else{
                            return true;
                        }
                    }
                }
                $this->addError($attribute, '手机号或邮箱错误');
            }],
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        $scenarios = parent::scenarios();
        $scenarios['invite'] = ['email'];
        return $scenarios;
    }

    /**
     * @inheritdoc
     */
    public function beforeSave($insert)
    {
        if ($insert && $this->token == '') {
            //$this->token = Yii::$app->security->generateRandomString(self::TOKEN_LENGTH);
            $this->token = (string)mt_rand(123000, 987650);
        }

        return parent::beforeSave($insert);
    }

    public function selfInvite()
    {
        $this->source = self::SOURCE_SELF;
        $this->language = Yii::$app->language;

        if ($this->allowSelfInvite() && $this->validate()) {
            $existingInvite = Invite::findOne(['email' => $this->email]);
            if ($existingInvite !== null) {
                //$existingInvite->delete();
                $date1 = strtotime($existingInvite->updated_at);
                $date2 = time();

                if( ($date2-$date1) > 3600 ){ //>24h
                    $existingInvite->created_at = date("Y-m-d H:i:s",time());
                    $existingInvite->smslimit = 1;
                }else{
                    if( $existingInvite->smslimit >= 5 ){
                        return '操作过于频繁，请稍后再试.';
                    }
                    //$existingInvite->smslimit += 1; // !!! 无并发能力
                }

                $this->beforeSave(true); //update token
                $existingInvite->token = $this->token;
                $existingInvite->updated_at = date("Y-m-d H:i:s",time());
                $existingInvite->smscount += 1;
                $existingInvite->cklimit = 1; //check sms = 1
//                return $existingInvite->save();
                if( $existingInvite->save() ){
                    return $this->sendInvitePhone();
                }
            }else{
                $this->created_at = date("Y-m-d H:i:s",time());
                $this->updated_at = date("Y-m-d H:i:s",time());
                $this->smslimit = 1;
                $this->smscount = 1;
                if( $this->save() ){
                    return $this->sendInvitePhone();
                }
            }
        }

        return false;
    }
    /**
     * 校验短信验证码
     *
     * @param String $type
     * @return Boolean
     */
    public function checkToken($token, $token_type){
        if( ! is_numeric($token) ){
            throw new \yii\web\BadRequestHttpException('手机号或验证码无效');
        }
        //验证类型 : ck仅验证 reg注册 repass找回密码 rname实名认证
        if( ! in_array($token_type, array('ck', 'reg', 'repass', 'rname')) ){
            throw new \yii\web\BadRequestHttpException('手机号或验证码无效');
        }
        $this->token_type = $token_type;
        //限制验证码有效期
        $sec = time() - strtotime($this->updated_at);
        //if( (strtotime($this->updated_at) + 180) < time() )
        if( $sec<=0 || $sec>3600 )
        {
            throw new \yii\web\BadRequestHttpException('验证码已失效.');
        }
        //限制校验次数
        $max_limit = 5;
        if( $this->cklimit >= $max_limit ){
            throw new \yii\web\BadRequestHttpException('验证码已失效.');
            throw new \yii\web\BadRequestHttpException('操作过于频繁，请稍后再试.');
        }
        if( $this->token==$token ){
            if( $this->token_type=='ck' ){
                //$this->token_token = md5(Yii::$app->user->id . $token .Yii::$app->request->userIP . Yii::$app->request->userAgent);
                $this->cklimit = new \yii\db\Expression('COALESCE(cklimit, 0) + 1');
            }else{
                $this->cklimit = $max_limit;
            }
            $this->token_token = md5(Yii::$app->user->id . $token .Yii::$app->request->userIP . Yii::$app->request->userAgent);
            if( ! $this->update() ){
                throw new \yii\web\BadRequestHttpException('手机号或验证码无效');
            }
            return true;
        }else{
            $this->cklimit = new \yii\db\Expression('COALESCE(cklimit, 0) + 1');
            $this->update();
            throw new \yii\web\BadRequestHttpException('手机号或验证码无效');
        }
    }
    /**
     * 配置短信接口
     */
    public function sendInvitePhone(){
        $_msg = $this->getMsg();
        if( ! $_msg ) return false;

        if( ! preg_match('/^(1)[0-9]{10}$/', $this->email) ){
            //send email
            return $this->sendInviteEmail();
        }

        $dir = explode('protected', dirname(__FILE__));
        $alifile = $dir[0].'/protected/vendor/aliyuncs/aliyun-php-sdk-core2/Config.php';
        if( is_file($alifile) ){
            include_once $alifile;
        }
        $iClientProfile = \DefaultProfile::getProfile("cn-beijing", self::ALI_accessKeyId, self::ALI_accessKeySecret);
        $client = new \DefaultAcsClient($iClientProfile);
        $request = new \Sms\Request\V20160927\SingleSendSmsRequest();
        $request->setSignName($_msg['sig']);
        $request->setTemplateCode($_msg['id']);
        $request->setRecNum($this->email);
        $request->setParamString('{"code":"'.$this->token.'","name":"UNI-CLASS"}');
        try {
            $response = $client->getAcsResponse($request);
            if ($response){
                if( $response->RequestId ){
                    return true;
                }
            }else{
                return '操作频繁，请稍后再试';
            }

        } catch (ClientException  $e) {
            //print_r($e->getErrorCode());   
            //print_r($e->getErrorMessage());   
        } catch (ServerException  $e) {
            //print_r($e->getErrorCode());   
            //print_r($e->getErrorMessage());
        }
        return false;

        try {
            $response = (Array)$client->getAcsResponse($request);
            if( isset($response['RequestId']) && isset($response['EnvId']) ){
                return true;
            }else{
                return false;
            }
            print_r($response);exit;
        }
        catch (ClientException  $e) {
            return false;
            print_r($e->getErrorCode());
            print_r($e->getErrorMessage());
        }
        catch (ServerException  $e) {
            return false;
            print_r($e->getErrorCode());
            print_r($e->getErrorMessage());
        }

    }
    public function sendInvitePhone_ali_dayu(){
        return false;
        $_msg = $this->getMsg();
        if( ! $_msg ) return false;

        if( ! preg_match('/^(1)[0-9]{10}$/', $this->email) ){
            //send email
            return $this->sendInviteEmail();
        }
        $SDK_DIR = dirname(__FILE__).'/sdk/';
        require_once($SDK_DIR . 'top/TopClient.php');
        require_once($SDK_DIR . 'top/ResultSet.php');
        require_once($SDK_DIR . 'top/RequestCheckUtil.php');
        require_once($SDK_DIR . 'top/request/AlibabaAliqinFcSmsNumSendRequest.php');
        //date_default_timezone_set('Asia/Shanghai'); 

        $c = new TopClient;
        $c->appkey = '23638811';
        $c->secretKey = '3495aae585a8420443ec934ff2127ce2';
        $c->format = 'json';
        $c->gatewayUrl = "https://eco.taobao.com/router/rest"; //default:http

        $req = new AlibabaAliqinFcSmsNumSendRequest;
        //$req->setExtend("123456");
        $req->setSmsType("normal");
        $req->setSmsFreeSignName($_msg['sig']);
        $req->setSmsTemplateCode($_msg['id']);
        $req->setSmsParam('{"code":"'.$this->token.'","product":"UNI-CLASS"}');
        $req->setRecNum($this->email);

        $resp = $c->execute($req);
        if( isset($resp->result) && $resp->result->err_code==0 ){
            return true;
        }
        return false;
    }
    /**
     * 获取短信／邮件内容
     * @param $type ='email', =''(sms)
     */
    private function getMsg($type=''){
        $codetype = (int)Yii::$app->request->post('codetype');
        if( $codetype==1 ){
            //注册
            if( $type=='email' ){
                return ['tit' => 'UNI-CLASS验证码', 'msg' => '验证码：'.$this->token.'，您正在UNI-CLASS进行邮箱验证，请勿将此号码告诉他人。'];
            }else{
                return ['sig' => '优涅教育', 'id'  => 'SMS_49045004'];  //阿里云
                //return ['sig' => '注册验证', 'id'  => 'SMS_47085061']; //大鱼
            }
        }elseif( $codetype==2 ){
            //找回密码
            if( $type=='email' ){
                return ['tit' => 'UNI-CLASS验证码', 'msg' => '验证码：'.$this->token.'，您正在UNI-CLASS进行邮箱验证，请勿将此号码告诉他人。'];
            }else{
                return ['sig' => '优涅教育', 'id'  => 'SMS_49045004'];  //阿里云
                //return ['sig' => '身份验证', 'id'  => 'SMS_47085059'];
            }
        }elseif( $codetype==3 ){
            //实名认证
            if( $type=='email' ){
                return ['tit' => 'UNI-CLASS验证码', 'msg' => '验证码：'.$this->token.'，您正在UNI-CLASS进行邮箱验证，请勿将此号码告诉他人。'];
            }else{
                return ['sig' => '优涅教育', 'id'  => 'SMS_49045004'];  //阿里云
                //return ['sig' => '身份验证', 'id'  => 'SMS_47085059'];
            }
        }else{
            return false;
        }
    }
    /**
     * 配置邮箱接口
     */
    public function sendInviteEmail(){
        $_msg = $this->getMsg('email');
        if( ! $_msg ) return false;

        $dir = explode('protected', dirname(__FILE__));
        $alifile = $dir[0].'/protected/vendor/aliyuncs/aliyun-php-sdk-core/Config.php';
        if( is_file($alifile) ){
            include_once $alifile;
        }

        $iClientProfile = \DefaultProfile::getProfile("cn-beijing", self::ALI_accessKeyId, self::ALI_accessKeySecret);
        $client = new \DefaultAcsClient($iClientProfile);
        $request = new \Dm\Request\V20151123\SingleSendMailRequest();
        $request->setAccountName("no-replay@uni-class.com");
        $request->setFromAlias("优涅教育");
        $request->setAddressType(1);
        //$request->setTagName("控制台创建的标签");
        $request->setReplyToAddress("false");
        $request->setToAddress($this->email);
        $request->setSubject($_msg['tit']);
        $request->setHtmlBody($_msg['msg']);
        try {
            $response = (Array)$client->getAcsResponse($request);
            if( isset($response['RequestId']) && isset($response['EnvId']) ){
                return true;
            }else{
                return false;
            }
//            print_r($response);exit;
        }
        catch (ClientException  $e) {
            return false;
            print_r($e->getErrorCode());
            print_r($e->getErrorMessage());
        }
        catch (ServerException  $e) {
            return false;
            print_r($e->getErrorCode());
            print_r($e->getErrorMessage());
        }
    }

    /**
     * 融云接口
     */
    public function RegRongyun($user){
        if( $user->u_rongyun ){
            return $user->u_rongyun;
        }
        if( ! $user ){
            return false;
        }
        if( ! $user->id ){
            return false;
        }
        $dir = explode('protected', dirname(__FILE__));
        $alifile = $dir[0].'/protected/vendor/rongyun/rongcloud.php';
        if( is_file($alifile) ){
            include_once $alifile;
        }else{
            return false;
        }
        $appKey    = 'cpj2xarlc44on';
        $appSecret = '5BQvu2GBBi';
        $jsonPath  = "jsonsource/";
        $RongCloud = new \RongCloud($appKey,$appSecret);

        // 获取 Token 方法
        $result = $RongCloud->user()->getToken($user->guid, $user->username, $user->getProfileImage()->getUrl());
        // 刷新用户信息方法
//        $result = $RongCloud->user()->refresh($user->guid, '', '');
        //print_r($result);
        $res = json_decode($result, true);
        if( $res['code'] == 200 ){
            $user->scenario = 'rongyun';
            $user->u_rongyun = $res['token'];
            if( $user->save() ){
                return $res['token'];
            }
            print_r($user->getErrors());
            return false;
        }else{
            return false;
        }
    }

    /**
     * Sends the invite e-mail
     */
    public function sendInviteMail()
    {
        $module = Yii::$app->moduleManager->getModule('user');
        $registrationUrl = Url::to(['/user/registration', 'token' => $this->token], true);

        // User requested registration link by its self
        if ($this->source == self::SOURCE_SELF) {

            $mail = Yii::$app->mailer->compose([
                'html' => '@humhub/modules/user/views/mails/UserInviteSelf',
                'text' => '@humhub/modules/user/views/mails/plaintext/UserInviteSelf'
            ], [
                'token' => $this->token,
                'registrationUrl' => $registrationUrl
            ]);
            $mail->setFrom([Yii::$app->settings->get('mailer.systemEmailAddress') => Yii::$app->settings->get('mailer.systemEmailName')]);
            $mail->setTo($this->email);
            $mail->setSubject(Yii::t('UserModule.views_mails_UserInviteSelf', 'Registration Link'));
            $mail->send();
        } elseif ($this->source == self::SOURCE_INVITE && $this->space !== null) {

            if($module->sendInviteMailsInGlobalLanguage) {
                Yii::$app->language = Yii::$app->settings->get('defaultLanguage');
            }

            $mail = Yii::$app->mailer->compose([
                'html' => '@humhub/modules/user/views/mails/UserInviteSpace',
                'text' => '@humhub/modules/user/views/mails/plaintext/UserInviteSpace'
            ], [
                'token' => $this->token,
                'originator' => $this->originator,
                'originatorName' => $this->originator->displayName,
                'token' => $this->token,
                'space' => $this->space,
                'registrationUrl' => $registrationUrl
            ]);
            $mail->setFrom([Yii::$app->settings->get('mailer.systemEmailAddress') => Yii::$app->settings->get('mailer.systemEmailName')]);
            $mail->setTo($this->email);
            $mail->setSubject(Yii::t('UserModule.views_mails_UserInviteSpace', 'Invitation to join: {space}', ['space' => $this->space->name]));
            $mail->send();

            // Switch back to users language
            if (Yii::$app->user->language !== "") {
                Yii::$app->language = Yii::$app->user->language;
            }
        } elseif ($this->source == self::SOURCE_INVITE) {

            // Switch to systems default language
            if($module->sendInviteMailsInGlobalLanguage) {
                Yii::$app->language = Yii::$app->settings->get('defaultLanguage');
            }

            $mail = Yii::$app->mailer->compose([
                'html' => '@humhub/modules/user/views/mails/UserInvite',
                'text' => '@humhub/modules/user/views/mails/plaintext/UserInvite'
            ], [
                'originator' => $this->originator,
                'originatorName' => $this->originator->displayName,
                'token' => $this->token,
                'registrationUrl' => $registrationUrl
            ]);
            $mail->setFrom([Yii::$app->settings->get('mailer.systemEmailAddress') => Yii::$app->settings->get('mailer.systemEmailName')]);
            $mail->setTo($this->email);
            $mail->setSubject(Yii::t('UserModule.invite', 'Invitation to join'));
            $mail->send();

            // Switch back to users language
            if (Yii::$app->user->language !== "") {
                Yii::$app->language = Yii::$app->user->language;
            }
        }
    }

    /**
     * Return user which triggered this invite
     *
     * @return \yii\db\ActiveQuery
     */
    public function getOriginator()
    {
        return $this->hasOne(\humhub\modules\user\models\User::className(), ['id' => 'user_originator_id']);
    }

    /**
     * Return space which is involved in this invite
     *
     * @return \yii\db\ActiveQuery
     */
    public function getSpace()
    {
        return $this->hasOne(\humhub\modules\space\models\Space::className(), ['id' => 'space_invite_id']);
    }

    /**
     * Allow users to invite themself
     *
     * @return boolean allow self invite
     */
    public function allowSelfInvite()
    {
        return (Yii::$app->getModule('user')->settings->get('auth.anonymousRegistration'));
    }

}
